<template>
  <div class="employees-container">
    <div class="app-container">
      <!-- 头部通用工具栏组件使用 -->
      <page-tools>
        <!-- 自定义左侧内容 -->
        <template #slot-left>
          <span>共 19 条记录</span>
        </template>
        <!-- 自定义右侧内容 -->
        <template #slot-right>
          <el-button
            v-power="'import'"
            type="danger"
            size="small"
            @click="uploadFn"
          >导入excel</el-button>
          <el-button
            v-power="'export'"
            type="success"
            size="small"
            @click="exportFn"
          >导出excel</el-button>
          <el-button
            type="primary"
            size="small"
            @click="addEmployeeFn"
          >新增员工</el-button>
        </template>
      </page-tools>
      <!-- 员工列表+分页 -->
      <el-card style="margin-top: 10px;">
        <el-table
          border
          :data="employeesList"
        >
          <el-table-column
            label="序号"
            type="index"
          />
          <el-table-column
            prop="username"
            label="姓名"
          />
          <el-table-column
            label="头像"
            prop="staffPhoto"
          >
            <template v-slot="{row}">
              <Image-hoder
                class="staffPhoto"
                :src="row.staffPhoto"
              /></template>
          </el-table-column>
          <el-table-column
            label="手机号"
            prop="mobile"
          />
          <el-table-column
            sortable
            :sort-method="workNumberSortFn"
            label="工号"
            prop="workNumber"
          />
          <el-table-column
            label="聘用形式"
            prop="formOfEmployment"
          >
            <!-- 使用插槽技术时，需要组件内变量，要用作用域插槽
            作用域插槽：
            (1)在组件内用<slot 属性名=‘组件内变量值’></slot> (table-column内部写好了这一步，变量名叫row)
            (2)再插槽内，用<tempalte v-slot='变量名'></tempalte> (变量会收集slot身上的属性和值形成一个对象)
            -->
            <!-- 条件表达式(只能用于true/false，如果有第三种值得情况，用枚举) -->
            <!-- 枚举：适用于一个值和多种情况比较，返回映射的值 -->

            <template v-slot="scope">
              <span>{{ formatter(scope.row) }}</span>
            </template>
          </el-table-column>

          <el-table-column
            label="部门"
            prop="departmentName"
          />
          <el-table-column
            label="入职时间"
            prop="timeOfEntry"
            :formatter="timeFormat"
          />
          <el-table-column
            label="操作"
            width="280"
          >
            <template v-slot="{row}">
              <el-button
                type="text"
                size="small"
                @click="lookDetailFn(row.id,row.formOfEmployment)"
              >查看</el-button>
              <el-button
                type="text"
                size="small"
                @click="assignRoleDialogFn(row)"
              >分配角色</el-button>
              <el-button
                type="text"
                size="small"
                @click="delEmployeeFn(row.id)"
              >删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <!-- 分页组件 -->
        <el-row
          type="flex"
          justify="center"
          align="middle"
          style="height: 60px"
        >
          <!-- 分页区域 -->
          <el-pagination
            :current-page="query.page"
            :page-sizes="[10, 15, 20, 25]"
            :page-size="query.size"
            layout="total, sizes, prev, pager, next, jumper"
            :total="total"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
          />
        </el-row>
      </el-card>
      <!-- 新增员工弹窗 -->
      <el-dialog
        title="新增员工"
        :visible.sync="showDialog"
        @close="addEmpDialogCloseFn"
      >
        <employee-form
          ref="empForm"
          :show.sync="showDialog"
          :tree-data="treeData"
          @addEmployeeEV="addEmloyeesFn"
        />
      </el-dialog>
      <!-- 角色分配弹窗 -->
      <!-- 员工-分配角色权限 - 弹窗 -->
      <el-dialog
        :show-close="false"
        title="分配角色"
        :visible="showRoleDialog"
      >
        <!-- 设置角色组件 -->
        <assign-role-dialog
          ref="assignRoleDialog"
          :show.sync="showRoleDialog"
          :all-role-list="allRoleList"
          @addRoleEv="addRoleFn"
        />
      </el-dialog>

    </div>
  </div>
</template>

<script>
// 导入组件
// import PageTools from '@/components/PageTools'  全局注册了就不用了
import { getEmloyeesListAPI, getDepartmentsListAPI, addEmloyeesAPI, delEmployeeAPI, getRoleAPI, getUserPhotoAPI, assignRolesAPI } from '@/api'
import Employees from '@/api/constant/index.js' // 导入枚举值
import dayjs from 'dayjs'
import employeeForm from './components/employeeForm.vue'
import AssignRoleDialog from './components/assignRoleDialog.vue'
// 树形结构的转换方法
import { transTree } from '@/utils'
export default {
  name: 'Employees',
  components: {
    // PageTools // 导入自定义组件
    employeeForm,
    AssignRoleDialog
  },
  data() {
    return {
      query: {
        page: 1, // 页码
        size: 10 // 每页条数
      },
      employeesList: [], // 员工列表
      total: 0, // 数据总条数
      // hireTypeList: Employees.hireType // 聘用形式
      showDialog: false, // 新增员工的弹窗(显示/隐藏)
      treeData: [], // 存储部门列表(树型结构)
      allEmployeeList: [], // 所有员工列表
      showRoleDialog: false,
      allRoleList: [], // 所有的角色列表
      clickEmpId: '' // 点击分配角色时，选中的员工id
    }
  },
  created() {
    // 获取员工列表方法
    this.getEmloyeesListFn()
    this.getDepartmentsListFn()
    this.getRoleFn()
  },
  methods: {
    // 获取员工列表数据
    async getEmloyeesListFn() {
      const res = await getEmloyeesListAPI(this.query)
      this.employeesList = res.data.rows // 页面表格里当前页码条数的数据
      this.total = res.data.total
      // 第二次请求，才是为了拿到所有的数据
      const allRes = await await getEmloyeesListAPI({
        page: 1,
        size: res.data.total // 上一个接口后台返回的总数量
      })
      // console.log(allRes)
      this.allEmployeeList = allRes.data.rows // 这个变量是为了给导出表格用的
    },
    // 请求部门列表
    async getDepartmentsListFn() {
      const res = await getDepartmentsListAPI()
      this.treeData = transTree(res.data.depts, '')
    },
    // 请求角色列表
    async getRoleFn() {
      const res = await getRoleAPI({
        page: 1,
        pagesize: 10 // 第一次不确定要多少条 先请求10条
      })
      console.log(res)
      const allRes = await getRoleAPI({
        page: 1,
        pagesize: res.data.total // 第二次再发一次，用第一次请求回来的总数据作为这一次条数
      })
      this.allRoleList = allRes.data.rows
    },
    // 每页显示的条数发生改变时触发
    handleSizeChange(newSize) {
      this.query.size = newSize
      this.getEmloyeesListFn()
    },
    // 当前页面发生改变时触发
    handleCurrentChange(newPage) {
      // 我点到第几页时，把这个页数付给传给后台的参数，让后台给我请求这一页的数据
      this.query.page = newPage
      this.getEmloyeesListFn()
    },
    // 格式化表格的某一项
    formatter(row) {
      // item是hireType里面的对象(id和value两个key)
      // hireTypeList.find(item =>item.id === row.formOfEmployment)把hireType里面id=1的对象返回在原地
      // 用数组的 find 方法找到 id = 1 的元素，再取出它的 value
      const obj = Employees.hireType.find(item => item.id === parseInt(row.formOfEmployment))
      return obj ? obj.value : '未知' // obj值为undefined，返回‘未知’
    },
    // 工号自定义排序方法
    workNumberSortFn(a, b) {
      // console.log(a, b) // a和b是表格对应行的数据(可以遍历到数组里所有对象)
      return parseInt(a.workNumber) - parseInt(b.workNumber)
    },
    // 时间格式化
    timeFormat(row) {
      return dayjs(row.timeOfEntry).format('YYYY-MM-DD')
    },
    // 添加员工点击事件方法
    addEmployeeFn() {
      this.showDialog = true
    },
    // 添加员工的请求
    async addEmloyeesFn(employeeObj) {
      await addEmloyeesAPI(employeeObj)
      this.getEmloyeesListFn()
    },
    // 关闭对话框事件方法
    addEmpDialogCloseFn() {
      // this.$refs.empForm 获取的是employeeForm组件对象，相当于拿到了employeeForm组件内this的值
      this.$refs.empForm.$refs.addForm.resetFields()
    },
    // 删除员工
    async delEmployeeFn(id) {
      await delEmployeeAPI(id)
      // 判断删除的是否是最后一个数据对象
      if (this.employeesList.length === 1) {
        this.query.page--
        // 假设后台要求传递的最小page只能是1
        // 解决：判断进入后，强制改回成1
        if (this.employeesList.length === 0) {
          this.query.page = 1
        }
      }
      this.getEmloyeesListFn()
    },
    // 导入excel按钮点击事件->为了跳转到excel上传的页面
    uploadFn() {
      this.$router.push('/excel')
    },
    // 导出excle按钮点击事件->为了自动下载带数据的excel文件
    exportFn() {
      // 这个import->懒加载
      import('@/vendor/Export2Excel').then(excel => {
        const tHeader = ['序号', '姓名', '头像', '手机号', '工号', '聘用形式', '部门', '入职时间', '转正时间', '密码', '转正状态']

        // 核心：把请求回来的数组套对象的数据，转成只有值得二维数组
        // Object.keys()
        // Object.values()->传入对象，返回所有值得的数组
        // 1、遍历数组里面的每个变量
        // const newArr = this.employeesList.map(obj => {
        //   return Object.values(obj)
        // })
        // 上面的问题：数据和头部纵向对应不上
        // 原因：Object.values取出的值是无序的，没办法和Theader按顺序对应
        // 解决：想尽一切办法，让我们的值，数组里的顺序和theader顺序对应上
        // 表格里和页面上的列只用到了8个，而数组里对象有11对key+value
        // 1、中文->英文的映射关系(枚举)
        // 序号在遍历的时候，就有索引值了，所以它的值不用去英文对象里获取
        const zhAndEnObj = {
          姓名: 'username',
          头像: 'staffPhoto',
          手机号: 'mobile',
          工号: 'workNumber',
          聘用形式: 'formOfEmployment',
          部门: 'departmentName',
          入职时间: 'timeOfEntry'
        }
        // 2、遍历每个英文对象
        // eslint-disable-next-line no-undef
        const data = this.allEmployeeList.map((enObj, index) => {
          // 3、遍历每个中文的key值
          const newArr = []
          tHeader.forEach(zhKey => {
            if (zhKey === '序号') {
              newArr.push(index + 1)
            } else {
              // eslint-disable-next-line no-undef
              const enValue = enObj[zhAndEnObj[zhKey]]
              if (zhAndEnObj[zhKey] === 'formOfEmployment') {
                const obj = Employees.hireType.find(item => item.id === parseInt(enValue))
                newArr.push(obj ? obj.value : '未知')
              } else {
                newArr.push(enValue)
              }
            }
          })
          return newArr
        })

        excel.export_json_to_excel({
          // 表格文件的列标题
          header: tHeader,
          // 表格里第二行开始的正文数据
          // 其中内层数组里直接写行的内容值
          data,
          // 导出时excel名字
          filename: '文件名',
          autoWidth: true,
          bookType: 'xlsx'
        })
      })
    },
    // 查看员工详情点击事件
    lookDetailFn(empId, formOfEmployment) {
      this.$router.push(`/employees/detail?id=${empId}&form=${formOfEmployment}`)
    },
    // 分配角色点击事件
    async assignRoleDialogFn(empObj) {
      this.showRoleDialog = true
      // 通过员工id，换回来员工详细信息(roleIds数组)
      const res = await getUserPhotoAPI(empObj.id)
      this.clickEmpId = empObj.id
      // this.$refs.assignRoleDialog.roleIdList = res.data.roleIds
      // Vue更新DOM的动作时异步的
      // 上一句话同步代码，会把所有同步代码执行完毕，才会更新真实DOM(弹窗才会出现)，假如立刻获取弹窗内容组件可能获取不到
      // this.$nextTick()作用：等待异步DOM更新完毕后，vue会回调()里函数体执行
      this.$nextTick(() => {
        this.$refs.assignRoleDialog.roleIdList = res.data.roleIds
      })
    },
    // 确认/取消按钮点击关闭弹窗事件
    // showFn() {
    //   this.showRoleDialog = false
    // }
    // 调用接口保存员工最新角色Id
    async addRoleFn(roleIdList) {
      const res = await assignRolesAPI({
        roleIds: roleIdList,
        id: this.clickEmpId
      })
      console.log(res)
    }
  }
}
</script>

<style lang="scss" scoped>
.staffPhoto {
  width: 100px;
  height: 100px;
  border-radius: 50%;
}
</style>

